package org.wevil.service.sys;

import org.wevil.entity.sys.SysOrg;
import org.wevil.params.update.OrgUP;
import org.wevil.repo.CondRoleOrgRepo;
import org.wevil.repo.sys.SysOrgRepo;
import org.wevil.util.BeanUtil;
import org.wevil.util.page.PageResult;
import org.wevil.util.page.PageResultUtil;
import org.wevil.vo.list.OrgListVo;
import org.wevil.vo.node.OrgNodeVo;
import org.wevil.vo.node.OrgNodeWxVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

@Service
@Transactional
public class OrgService {
    
    @Resource
    private SysOrgRepo repo;
    @Resource
    private CondRoleOrgRepo condRoleOrgRepo;

    /** 根据id获取信息 */
    public org.wevil.vo.list.OrgListVo getById(Integer orgId){
        Optional<SysOrg> opt = repo.findById(orgId);
        if(opt.isPresent()){
            SysOrg entity = opt.get();
            org.wevil.vo.list.OrgListVo vo = new org.wevil.vo.list.OrgListVo();
            BeanUtil.copyPropIgnoreNull(entity, vo);
            return vo;
        }
        return null;
    }

    /** 分页 */
    public PageResult<OrgListVo> page(org.wevil.params.page.OrgPP param) {
        // 要查询的字段
        String orgName = param.getOrgName();
        Integer current = param.getCurrent();
        Integer size = param.getSize();
        Specification<SysOrg> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotBlank(orgName)) {
                predicates.add(cb.like(root.get("orgName").as(String.class), "%" + orgName + "%"));
            }
            predicates.add(cb.equal(root.get("del").as(String.class), "N"));
            return cb.and(predicates.toArray(new Predicate[0]));
        };
        Sort sort = Sort.by(Sort.Direction.DESC, "ts");
        Pageable pageable = PageRequest.of(current - 1, size, sort);
        Page<SysOrg> page = repo.findAll(specification, pageable);
        // 封装返回数据
        Iterator<SysOrg> iterator = page.iterator();
        List<OrgListVo> voList = new ArrayList<>();
        while (iterator.hasNext()) {
            SysOrg next = iterator.next();
            OrgListVo dto = new OrgListVo();
            BeanUtil.copyPropIgnoreNull(next, dto);
            voList.add(dto);
        }
        // 返回
        long total = repo.count(specification);
        return PageResultUtil.generateResult(voList, current, size, total);
    }

    /** 获取组织名称 */
    public String getOrgName(Integer orgId){
        Optional<SysOrg> optional = repo.findById(orgId);
        return optional.map(SysOrg::getName).orElse(null);
    }

    /** 查询是否有下级菜单 */
    public boolean haveLowerLevel(Integer menuId){
        Integer count = repo.countByPid(menuId);
        return count > 0;
    }

    /** 获取组织名称列表根据id */
    public List<String> gerOrgNamesByOrgIdIn(List<Integer> orgIds) {
        return repo.findOrgNameByOrgIdIn(orgIds);
    }

    /** 获取组织列表 */
    public List<org.wevil.vo.list.OrgListVo> getOrgList() {
        List<SysOrg> orgs = repo.findAll();
        List<org.wevil.vo.list.OrgListVo> vos = new ArrayList<>();
        orgs.forEach(entity -> vos.add(entity2vo(entity)));
        return vos;
    }

    /** 获取下级组织列表 */
    public List<org.wevil.vo.list.OrgListVo> getSubOrgList(Integer orgId) {
        List<SysOrg> orgs = repo.findByPid(orgId);
        List<org.wevil.vo.list.OrgListVo> vos = new ArrayList<>();
        orgs.forEach(entity -> vos.add(entity2vo(entity)));
        return vos;
    }

    /**
     * 获取组织节点
     *
     * @author wanglei
     * @since 2022/2/9
     * */
    public List<OrgNodeVo> getOrgNodeList() {
        List<SysOrg> orgs = repo.findAll();
        List<OrgNodeVo> orgNodeVos = new ArrayList<>();
        orgs.forEach(org -> orgNodeVos.add(entity2NodeVo(org)));
        return orgNodeVos;
    }

    public List<OrgNodeWxVo> getOrgNodeWxList() {
        List<SysOrg> orgs = repo.findAll();
        List<OrgNodeWxVo> orgNodeVos = new ArrayList<>();
        orgs.forEach(org -> orgNodeVos.add(entity2NodeWxVo(org)));
        return orgNodeVos;
    }

    /** 添加组织 */
    public void addOrg(SysOrg sysOrg) {
        repo.save(sysOrg);
    }

    /** 删除组织 */
    public void delOrg(Integer orgId) {
        Optional<SysOrg> optional = repo.findById(orgId);
        if(optional.isPresent()){
            condRoleOrgRepo.deleteByOrgId(orgId);
            condRoleOrgRepo.flush();
            repo.deleteById(orgId);
        }
    }

    /** 更新组织 */
    public void updateOrg(OrgUP param) {
        SysOrg entity = new SysOrg();
        BeanUtil.copyPropIgnoreNull(param, entity);
        repo.update(entity);
    }

    // -----------------------------------------私有方法---------------------------------------//

    /** 实体转vo */
    private org.wevil.vo.list.OrgListVo entity2vo(SysOrg entity){
        org.wevil.vo.list.OrgListVo vo = new org.wevil.vo.list.OrgListVo();
        BeanUtil.copyPropIgnoreNull(entity, vo);
        return vo;
    }

    /**
     * 实体转节点vo
     *
     * @author wanglei
     * @since 2022/2/9
     * */
    private OrgNodeVo entity2NodeVo(SysOrg sysOrg){
        OrgNodeVo orgNodeVo = new OrgNodeVo();
        BeanUtil.copyPropIgnoreNull(sysOrg, orgNodeVo);
        orgNodeVo.setId(sysOrg.getId());
        orgNodeVo.setName(sysOrg.getName());
        return orgNodeVo;
    }

    /** 实体转小程序节点vo */
    private OrgNodeWxVo entity2NodeWxVo(SysOrg entity) {
        OrgNodeWxVo vo = new OrgNodeWxVo();
        BeanUtil.copyPropIgnoreNull(entity, vo);
        vo.setId(entity.getId());
        vo.setValue(entity.getId().toString());
        vo.setName(entity.getName());
        vo.setText(entity.getName());
        return vo;
    }
}
